import socket
import threading
import datetime
import time
import logging
import random

FORMAT = "line-->%(lineno)d  %(threadName)s %(message)s"
logging.basicConfig(format=FORMAT, level=logging.DEBUG)


class Server:
    S_CHAR = '&#&#&'
    ENCODING = 'GBK'
    STR = S_CHAR.join(["{}"] * 6)
    SHOW_PEOPLE = 'show_people'
    REGISTER = "register"
    LOGIN = 'login'

    def __init__(self, ip: str = '127.0.0.1', port: int = 60000):
        # 设置ip，port
        self.address = ip, port
        # 创建socket对象
        self.sock = socket.socket()
        self.event = threading.Event()
        # 所有的已经连接的socket，用户
        self.clients = {}
        self.groups = {}
        self.lock = threading.Lock()
        self.crate_id = [str(i) for i in range(10)]
        self.FORMAT = {
            'name': None,
            'uuid': None,
            'data': None,
            'method': None,
            'password': None,
            'ok':None
        }

    def start(self):
        # 对本地socket进行ip与port的绑定
        self.sock.bind(self.address)
        # 让此socket进行监听，参数是可以接收的连接数，量比较少的时候可以写0
        self.sock.listen(False)
        # 设置为daemon线程，那么服务想要中断的时候，就会直接退出了
        threading.Thread(target=self.accept, name="accept", daemon=True).start()

    def register(self, name, rid, password, sock):
        data = name, [password], rid, sock
        uuid = ''.join(random.choices(self.crate_id, k=10))
        logging.info(uuid)
        self.FORMAT['name'] = name
        self.FORMAT['uuid'] = rid
        self.FORMAT['password'] = password
        self.clients.setdefault(uuid, data)
        return uuid

    def judge(self, data, sock: socket.socket):
        name, rid, data, method, password, ok = data.decode(self.ENCODING).split(self.S_CHAR)
        logging.info(f"{name}--{rid}--{data}--{method}--{password}--{ok}")

        if method == self.SHOW_PEOPLE:
            self.FORMAT['data'] = self.show_people
            logging.info(
                self.STR.format(*self.FORMAT))
            sock.send(
                self.STR.format(*self.FORMAT.values()).encode(self.ENCODING))
            logging.info("成功发送")
            self.FORMAT['data'] = None

        elif method == self.REGISTER:
            print('in 72')
            self.FORMAT['uuid'] = self.register(name, rid, password, sock)
            sock.send(self.STR.format(*self.FORMAT.values()).encode(self.ENCODING))
            self.FORMAT['uuid'] = None

        elif method == self.LOGIN:
            self.login(rid, password)
            logging.info(f"in login method   {self.FORMAT['ok']}")
            sock.send(self.STR.format(*self.FORMAT.values()).encode(self.ENCODING))

        elif rid in self.clients:  # TODO
            logging.info(data.decode(self.ENCODING))
            self.data = data
            self.clients.get(rid, sock).send(
                self.STR.format(*self.FORMAT.values()).encode(self.ENCODING)
            )

    def recv(self, sock: socket.socket):
        # 不断的等待远端的信息
        while True:
            try:
                data = sock.recv(1024)
                if not data or data.strip() == b'q':
                    logging.info(f"data--> {data}{sock.getpeername()}logout~~~")
                    sock.close()
                    break
            except ConnectionResetError:
                logging.info(f"{sock.getpeername()}logout~~~")
                sock.close()
                break
            # 对数据进行截取分割筛选等，组成自己的格式，格式应该复杂一点
            self.judge(data, sock)

    def login(self, rid, password):
        print('有这个人', self.clients[rid][0], password)
        if rid in self.clients:
            print('有这个人', self.clients[rid][0], password)
            if self.clients[rid][0] == password:
                self.FORMAT['ok'] = True
                print('登陆成功了呀')

    @property
    def show_people(self):
        logging.info(f'{self.clients.keys()}------------------------------')
        return self.clients.keys()

    def stop(self):
        """此方法是服务器关机的时候，或者停止服务的时候才会进行的操作，其实很少会用到"""
        # 先将按钮置为True，这样别的就可以停止工作了，其实没啥用，因为他们都在别的地方进行阻塞，如accept跟recv
        self.event.set()
        # 锁住用户信息，并将之资源进行清理
        with self.lock:
            for user in self.clients.values():
                user.close()
            self.clients.clear()
        self.sock.close()

    def accept(self):
        # 当event还没有被置为True时，我们需要一直准备接受远端的连接，需要在一个独立的线程中运行
        while not self.event.is_set():
            # 返回远端的socket对象，和远端的地址
            # 有新人，那么应该将他加入到用户字典中
            rsock, raddr = self.sock.accept()
            # 打印一下
            logging.info(f"{raddr}")
            # 将这个已经建立好的连接放到另一个线程中运行
            # 设置为daemon线程，那么服务想要中断的时候，就会直接退出了
            threading.Thread(target=self.recv, args=(rsock,), name="recv", daemon=True).start()

    def create_group(self):
        pass

    def manage(self):
        pass


if __name__ == '__main__':
    server = Server()
    server.start()
    while not server.event.is_set():
        cmd = input('>>>').strip()
        if cmd == 'q':
            server.event.set()
            logging.info('正在清理资源~~~')
            time.sleep(1)
            break
        else:
            logging.info(f"当前线程有{threading.active_count()}个")


logging.info('===end===')
